package cn.edu.hnu.gpg.api;

import cn.edu.hnu.gpg.api.error.InternalException;
import cn.edu.hnu.gpg.api.error.NotFoundException;
import cn.edu.hnu.gpg.api.error.PermissionDeniedException;
import cn.edu.hnu.gpg.api.error.UnknownException;
import cn.edu.hnu.gpg.dto.StudentDocumentInfo;
import cn.edu.hnu.gpg.entity.Student;
import cn.edu.hnu.gpg.entity.Teacher;
import cn.edu.hnu.gpg.entity.UploadedFile;
import cn.edu.hnu.gpg.entity.User;
import cn.edu.hnu.gpg.entity.enums.UserType;
import cn.edu.hnu.gpg.service.StudentDocService;
import cn.edu.hnu.gpg.service.StudentService;
import cn.edu.hnu.gpg.service.SupervisionService;
import cn.edu.hnu.gpg.service.TeacherService;
import cn.edu.hnu.gpg.util.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

@Controller
public class StudentDocApiController {

    private final static String STUDENT_DOC_DIR = "student_doc/";
    private final static Logger logger = LogManager.getLogger(StudentDocApiController.class);

    @Autowired
    private StudentDocService studentDocService;
    @Autowired
    private StudentService studentService;
    @Autowired
    private TeacherService teacherService;
    @Autowired
    private SupervisionService supervisionService;

    @RequestMapping(value = "/api/studentDoc/upload/{phase_id}", method = RequestMethod.POST)
    @ResponseBody
    public Integer uploadStudentDocument(HttpServletRequest request, @PathVariable(name = "phase_id") Integer phaseId) throws PermissionDeniedException, UnknownException {
        User user = ((User) request.getSession(false).getAttribute("user"));
        if (user.getUserType() != UserType.S)
            throw new PermissionDeniedException("Only student can upload student document");

        //将当前上下文初始化给  CommonsMultipartResolver （多部分解析器）
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
                request.getSession().getServletContext());
        //检查form中是否有enctype="multipart/form-data"
        if (multipartResolver.isMultipart(request)) {
            //将request变成多部分request
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;
            String fileName = multiRequest.getFileNames().next();
            MultipartFile file = multiRequest.getFile(fileName);
            try {
                return studentDocService.createOrReplace(STUDENT_DOC_DIR, ((CommonsMultipartFile) file).getFileItem().getName(), file,
                        studentService.findStudentByUserId(user.getUserId()).getStudentId(), phaseId);
            } catch (Exception e) {
                logger.debug(e.getMessage());
                throw new UnknownException();
            }
        }
        return null;
    }

    @RequestMapping(value = "/studentDoc/download/{fileId}", method = RequestMethod.GET)
    public ResponseEntity<byte[]> downloadFile(HttpServletRequest request, @PathVariable Integer fileId) throws NotFoundException, InternalException, PermissionDeniedException {

        StudentDocumentInfo fileRecord = studentDocService.queryDocumentInfo(fileId);
        if (fileRecord == null)
            throw new NotFoundException("Requested file not found");

        // 控制下载权限
        User user = ((User) request.getSession().getAttribute("user"));
        if (user.getUserType() == UserType.S) {
            Student student = studentService.findStudentByUserId(user.getUserId());
            if (student == null || !student.getStudentId().equals(fileRecord.getStudentId()))
                throw new PermissionDeniedException();

        } else if (user.getUserType() == UserType.T) {
            Teacher teacher = teacherService.findTeacherByUserId(user.getUserId());
            if (teacher == null)
                throw new PermissionDeniedException();

            List<Integer> idList = supervisionService.findStudentIdByTeacher(teacher);
            boolean found = false;
            for (Integer id : idList) {
                if (id.equals(fileRecord.getStudentId())) {
                    found = true;
                    break;
                }
            }

            if (!found)
                throw new PermissionDeniedException();
        }

        try {
            HttpHeaders headers = new HttpHeaders();
            File file = new File(STUDENT_DOC_DIR, fileId.toString());

            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", new String(fileRecord.getFileName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
            return new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
        } catch (IOException e) {
            logger.debug(e.getMessage());
            throw new InternalException();
        }
    }
}
